/*******************************************************************************
 ** 
 ** This file is part of cmemtrac
 ** (C) 2011 Kevin Druelle 
 **
 ** Cmemtrac is free software: you can redistribute it and/or modify
 ** it under the terms of the GNU Lesser General Public License as published by
 ** the Free Software Foundation, either version 3 of the License, or
 ** (at your option) any later version.
 ** 
 ** Cmemtrac is distributed in the hope that it will be useful,
 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ** GNU General Public License for more details.
 ** 
 ** You should have received a copy of the GNU General Public License
 ** along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 ** 
 ******************************************************************************/

#include <stdlib.h>
#include "cmt_alloc.h"
#include "cstack.h"
#include "clist.h"

#pragma pack(1)
typedef struct {
    const char * fileName;
    const char * functionName;
    unsigned long line;
    size_t size;
}sAllocInfo;
#pragma pop

cstack_t scopeStack = NULL;


void cmt_enterscope(){
    clist_t scope;
    if(scopeStack == NULL){
        cstack_init(&scopeStack);
    }
    clist_init(&scope);
    cstack_push(&scopeStack, scope);
}


void * cmt_malloc
(const char * szFileName, const char * szFuncName, unsigned long ulLine, size_t sAllocSize){
    clist_t list;
    size_t sTotalAllocSize = 0;
    void * ptr;
    
    sTotalAllocSize = sAllocSize + sizeof(sAllocInfo);
    
    if(scopeStack == NULL){ //no need to trac memory
        return malloc(sAllocSize);
    }
    if(cstack_getSize(&scopeStack) == 0){ // no need to trac memory
        return malloc(sAllocSize);
    }
    
    list = cstack_top(&scopeStack);
    
    ptr = malloc(sTotalAllocSize);        
    
    ((sAllocInfo*)ptr)->fileName = szFileName;
    ((sAllocInfo*)ptr)->functionName = szFuncName;
    ((sAllocInfo*)ptr)->line = ulLine;
    ((sAllocInfo*)ptr)->size = sAllocSize;
    
    clist_pushBack(&list, ptr + sizeof(sAllocInfo));
    
    return ptr + sizeof(sAllocInfo);
}


void cmt_free(void * ptr){
    clist_t scope;
    sAllocInfo * infos;
    
    if(scopeStack == NULL){
        return free(ptr);
    }
    if(cstack_getSize(&scopeStack) == 0){
        return free(ptr);
    }
    
    scope = cstack_top(&scopeStack);
    infos = ptr - sizeof(sAllocInfo);
    
    clist_remove(&scope, ptr);
    
    free(ptr - sizeof(sAllocInfo));
}

